package com.nulldev.util.web.nTube.pages;

import static com.nulldev.util.web.nTube.pages.Urlizer.decodeUrlizer;

import java.time.Duration;
import java.util.List;
import java.util.Map;

import com.nulldev.util.JVM.Arguments;
import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.concurrency.threadIt.v4.emapi.ExecutorManager;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.web.HttpClient.HttpClient;
import com.nulldev.util.web.HttpServer3.Response;
import com.nulldev.util.web.HttpServer3.pages.v3.HttpPage3;
import com.nulldev.util.web.URLUtils.URLUtils;
import com.nulldev.util.web.YouTubeExtractor.subtitles.SRTBuilder;
import com.nulldev.util.web.YouTubeExtractor.subtitles.Subtitle;
import com.nulldev.util.web.YouTubeExtractor.subtitles.SubtitleParser;
import com.nulldev.util.web.YouTubeExtractor.subtitles.SubtitleParser.FMTVersion;

public class SRTGeneratorPage extends HttpPage3 {

	public static final boolean USE_JSON_API = Arguments.notArguments("--Subtitles.legacyAPI");
	private static final Logger log = LoggerFactory.getLoggerD(Arguments.hasArgument("--debug", "--trace"));
	private static final String e = "&fmt=json3";

	public SRTGeneratorPage() {
		super("/srt_gen");
	}

	@SuppressWarnings("resource")
	@Override
	public Response onRequest(final Request request) {
		final Map<String, String> s = URLUtils.parseQuery(request.url());
		if (s == null) {
			log.error("Query url failed and returned null!");
			return new Response(503).requestKeepAliveDisable(true);
		}
		if ((!s.containsKey("url") && !s.containsKey("uzc"))) {
			log.debug("Dropped SRT request: No urlizer URL found.");
			log.debug("Got: " + request.url());
			return new Response(403);
		}
		final String link = decodeUrlizer(request.url()); // FIXME: huh
		if (!link.startsWith("https://www.youtube.com") && !link.startsWith("https://youtube.com")) {
			log.warn("Dropped invalid subtitle URL: " + link);
			return new Response(403);
		}
		final String format = StringsUtil.substringBetweenO(link, "&fmt=", "&");
		FMTVersion formatVer = FMTVersion.get(format);
		if (formatVer == FMTVersion.UNKNOWN) {
			formatVer = FMTVersion.JSON3;
			log.warn("Got unknown format, assuming JSON3.");
		}
		try {
			if (USE_JSON_API || s.containsKey("useJSON")) {
				final long start = System.currentTimeMillis();
				log.debug("[SRT]>prepare");
				final String data = HttpClient.getString().url(link + e).timeout(Duration.ofSeconds(60)).create().dataThenClose();
				log.debug("[SRT]>getData: " + (System.currentTimeMillis() - start) + " ms");
				final List<Subtitle> subtitles = SubtitleParser.getSubtitlesF(data, formatVer);
				log.debug("[SRT]>getSubtitlesF: " + (System.currentTimeMillis() - start) + " ms");
				final SRTBuilder builder = new SRTBuilder();
				log.debug("[SRT]>builder: " + (System.currentTimeMillis() - start) + " ms");
				builder.addAll(subtitles);
				log.debug("[SRT]>appendSubtitles: " + (System.currentTimeMillis() - start) + " ms");
				ExecutorManager.globalAsyncSubmit(() -> {
					subtitles.clear();
					log.debug("[SRT]>clearSubtitles-late: " + (System.currentTimeMillis() - start) + " ms");
					return null;
				});
				return new Response(200, createStream(builder.build())).setCustomMime("application/x-subrip");
			} else {
				final String data = HttpClient.getString().url(link).timeout(Duration.ofSeconds(60)).create().dataThenClose();

				final List<Subtitle> subtitles = SubtitleParser.getSubtitlesF(data, formatVer);
				final SRTBuilder builder = new SRTBuilder();
				for (final Subtitle t : subtitles) {
					builder.add(t);
				}
				ExecutorManager.globalAsyncSubmit(() -> {
					subtitles.clear();
					return null;
				});
				return new Response(200, createStream(builder.build())).setCustomMime("application/x-subrip");
			}
		} catch (Exception e) {
			JVM.errorln(e);
			return new Response(403);
		}
	}

}
